﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Slock.GameObjects.ActorComponents
{
    public class BoundingBoxCollisionComponent : CollisionComponent
    {
        private BoundingBox boundingBox;

        /// <summary>
        /// Initializes a new instance of BoundingCollisionComponent using the min and max for bounds
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        public BoundingBoxCollisionComponent(Actor owner,ref Vector3 min, ref Vector3 max) : base(ref owner)
        { this.boundingBox = new BoundingBox(min, max); }

        /// <summary>
        /// Initializes a new instance of BoundingBoxCollisionComponent using the specified bounding box
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="bounding"></param>
        public BoundingBoxCollisionComponent(Actor owner, BoundingBox bounding)
            : this(owner,ref bounding.Min,ref bounding.Max)
        { }

        /// <summary>
        /// Initializes a new instance of BoundingCollisionComponent using the min and max for bounds
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        public BoundingBoxCollisionComponent(Actor owner, Vector3 min, Vector3 max)
            : this(owner, ref min, ref max)
        { }

        /// <summary>
        /// Initializes a new instance of BoundingCollisionComponent using a location and a size
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="location"></param>
        /// <param name="size"></param>
        public BoundingBoxCollisionComponent(Actor owner, Vector3 location, float size) : base(ref owner)
        {
            Vector3 diagonalVector = new Vector3(size / 2.0f);
            this.boundingBox = new BoundingBox(location - diagonalVector, location + diagonalVector);
        }

        public override bool Intersecting(Microsoft.Xna.Framework.BoundingBox box)
        { return box.Intersects(boundingBox); }

        public override bool Intersecting(Microsoft.Xna.Framework.BoundingFrustum frustum)
        { return frustum.Intersects(boundingBox); }

        public override bool Intersecting(Microsoft.Xna.Framework.BoundingSphere sphere)
        { return sphere.Intersects(boundingBox); }

        public override bool Intersecting(Microsoft.Xna.Framework.Plane plane)
        { return boundingBox.Intersects(plane) == PlaneIntersectionType.Intersecting; }

        public override bool Intersecting(Microsoft.Xna.Framework.Ray ray)
        { return ray.Intersects(boundingBox).HasValue; }

        public override ContainmentType Contains(BoundingBox box)
        { return box.Contains(box); }

        public override ContainmentType Contains(Ray ray)
        {
            float? distance = ray.Intersects(boundingBox);

            if (distance.HasValue)
            {
                return ContainmentType.Intersects;
            }
            else
                return ContainmentType.Disjoint;
        }

        public override ContainmentType Contains(BoundingSphere sphere)
        { return sphere.Contains(boundingBox); }

        public override PlaneIntersectionType Contains(Plane plane)
        { return plane.Intersects(boundingBox); }

        public override void UpdatePrimitive()
        { }

        public BoundingBox BoundingBox
        {
            get { return this.boundingBox; }
            set { this.boundingBox = value; }
        }
    }
}
